package com.smart.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.common.PageInfo;
import com.smart.common.domain.BaseEntity;
import com.smart.common.enums.OperateModuleEnum;
import com.smart.common.enums.OperateTypeEnum;
import com.smart.common.service.LogService;
import com.smart.common.utils.AssertUtil;
import com.smart.mapper.OperateUserMapper;
import com.smart.mapper.OperateUserRoleMapper;
import com.smart.model.convert.OperateRoleConvert;
import com.smart.model.convert.OperateUserConvert;
import com.smart.model.domain.OperateRoleDO;
import com.smart.model.domain.OperateUserDO;
import com.smart.model.domain.OperateUserRoleDO;
import com.smart.model.dtomapper.OperateUserDtoMapper;
import com.smart.model.request.OperateUserAddRequest;
import com.smart.model.request.OperateUserRequest;
import com.smart.model.request.OperateUserUpDatePasswordRequest;
import com.smart.model.request.OperateUserUpDateStatusRequest;
import com.smart.model.request.OperateUserUpdateRequest;
import com.smart.model.vo.OperateUserVO;
import com.smart.service.OperateUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;

/**
 * @author zhanghong
 */
@Service
public class OperateUserServiceImpl extends ServiceImpl<OperateUserMapper, OperateUserDO> implements OperateUserService {
    @Autowired
    private OperateUserMapper operateUserMapper;
    @Autowired
    private OperateUserRoleMapper operateUserRoleMapper;
    @Autowired
    private LogService logService;

    @Override
    public OperateUserVO getByKey(long id) {
        OperateUserDO operateUserDO = getById(id);
        OperateUserVO operateUserVO = OperateUserDtoMapper.INSTANCE.do2VO(operateUserDO);
        return operateUserVO;
    }

    @Override
    public PageInfo<OperateUserVO> pageQuery(OperateUserRequest request) {
        long count = operateUserMapper.pageCount(request);
        List<OperateUserDO> list = operateUserMapper.pageQuery(request, request.getPageSize(), request.fetchOffSet());
        List<OperateUserVO> operateUserVOList = OperateUserConvert.buildOperateUserVoList(list);
        fillInfo(operateUserVOList);
        return new PageInfo(request.getPageNum(), request.getPageSize(), operateUserVOList, count);
    }

    private void fillInfo(List<OperateUserVO> operateUserVOList) {
        for (OperateUserVO operateUserVO : operateUserVOList) {
            // 查询当前用户所关联的角色
            List<OperateRoleDO> roleDOS = operateUserRoleMapper.listByUserId(operateUserVO.getId());
            operateUserVO.setRoles(OperateRoleConvert.buildOperateRoleVoList(roleDOS));
        }
    }

    @Override
    public List<OperateUserVO> listQuery(OperateUserRequest request) {
        List<OperateUserDO> list = lambdaQuery().eq(BaseEntity::getDeleted, 0).list();
        List<OperateUserVO> operateUserVOS = OperateUserConvert.buildOperateUserVoList(list);
        return operateUserVOS;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(OperateUserAddRequest request) {
        AssertUtil.assertNotEmpty(request.getRoleIds(), "角色权限不能为空");
        OperateUserDO operateUserDO = OperateUserDtoMapper.INSTANCE.request2DO(request);
        Integer count = operateUserMapper.selectDOByUserName(request.getAccount());
        AssertUtil.assertTrue(count<1,"用户名已存在，请更换一个");
        operateUserDO.setPassword(request.getAccount());
        boolean save = save(operateUserDO);
        AssertUtil.assertTrue(save, "新增用户失败");

        for (Long roleId : request.getRoleIds()) {
            OperateUserRoleDO operateUserRole = new OperateUserRoleDO();
            operateUserRole.setRoleId(roleId);
            operateUserRole.setUserId(operateUserDO.getId());
            operateUserRoleMapper.insertDO(operateUserRole);
        }

        //记录操作日志
        logService.logOperatePlatformAddScene(OperateModuleEnum.账号管理, OperateTypeEnum.新建, operateUserDO.getId(), JSON.toJSONString(getById(operateUserDO.getId())));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByKey(OperateUserUpdateRequest request) {
        String beforeContent = JSON.toJSONString(getById(request.getId()));
        AssertUtil.assertNotEmpty(request.getRoleIds(), "角色权限不能为空");
        OperateUserDO operateUserDO = OperateUserDtoMapper.INSTANCE.request2DO(request);
        boolean update = saveOrUpdate(operateUserDO);
        AssertUtil.assertTrue(update, "编辑用户失败");
        //先删后写
        operateUserRoleMapper.deleteDOByUserId(operateUserDO.getId());
        for (Long roleId : request.getRoleIds()) {
            OperateUserRoleDO operateUserRole = new OperateUserRoleDO();
            operateUserRole.setRoleId(roleId);
            operateUserRole.setUserId(operateUserDO.getId());
            operateUserRoleMapper.insertDO(operateUserRole);
        }

        //记录操作日志
        String afterContent = JSON.toJSONString(getById(operateUserDO.getId()));
        logService.logOperatePlatform(OperateModuleEnum.账号管理, OperateTypeEnum.修改, operateUserDO.getId(), beforeContent, afterContent);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updatePasswordByKey(OperateUserUpDatePasswordRequest request) {
        OperateUserDO operateUserDO = operateUserMapper.selectDOById(request.getId());
        AssertUtil.assertNotNull(operateUserDO, "用户不存在");
        operateUserDO.setPassword(request.getPassword());
        saveOrUpdate(operateUserDO);

        //记录操作日志
        String beforeContent = JSON.toJSONString(operateUserDO);
        String afterContent = JSON.toJSONString(getById(operateUserDO.getId()));
        logService.logOperatePlatform(OperateModuleEnum.账号管理, OperateTypeEnum.修改, operateUserDO.getId(), beforeContent, afterContent, "修改密码");
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatus(OperateUserUpDateStatusRequest request) {
        OperateUserDO operateUserDO = operateUserMapper.selectDOById(request.getId());
        AssertUtil.assertNotNull(operateUserDO, "用户不存在");
        operateUserDO.setStatus(request.getStatus());
        saveOrUpdate(operateUserDO);

        //记录操作日志
        String beforeContent = JSON.toJSONString(operateUserDO);
        String afterContent = JSON.toJSONString(getById(operateUserDO.getId()));
        String description = String.format("状态启用/禁用", Objects.equals(request.getStatus(), "ENABLE") ? "启用" : "禁用");
        logService.logOperatePlatform(OperateModuleEnum.账号管理, OperateTypeEnum.修改, operateUserDO.getId(), beforeContent, afterContent, description);
        return true;
    }
}
